import 'dart:math' as math;

import 'package:boss/color_constant.dart';
import 'package:boss/textStyle/text_style.dart';
import 'package:hi_common/hi_common.dart';
import 'package:flutter/material.dart';
import 'dart:math' as math;

final List<List<Color>> _colors = [
  [ColorConstant.fbd43, ColorConstant.fe7f76],
  [ColorConstant.fe337d, ColorConstant.f6abb],
  [ColorConstant.f4ebe, ColorConstant.f88dd],
  [ColorConstant.fb787e, ColorConstant.fc7cf],
  [ColorConstant.f5ba0, ColorConstant.fd4e4],
  [ColorConstant.f7a38, ColorConstant.fbe9e],
  [ColorConstant.fc031, ColorConstant.fd05f],
  [ColorConstant.be850, ColorConstant.af2b4],
  [ColorConstant.d5ec68, ColorConstant.e7edc7],
  [ColorConstant.cdc61, ColorConstant.bfad4],
  [ColorConstant.afb9e, ColorConstant.a1ffe3],
  [ColorConstant.ff38, ColorConstant.ffcd],
  [ColorConstant.f1c89fe, ColorConstant.f71b5ff],
  [ColorConstant.ff0dc2ff, ColorConstant.ff75d6ff],
  [ColorConstant.ffb8effc, ColorConstant.ff07cdfc],
  [ColorConstant.ffe741ff, ColorConstant.ffff9ef7],
  [ColorConstant.f645cff, ColorConstant.ffbb80f4],
  [ColorConstant.ffaa3ae0, ColorConstant.ffd2aef4],
  [ColorConstant.ffab67ff, ColorConstant.ffdbd1ff],
  [ColorConstant.ff733be5, ColorConstant.ffd6b1ff],
];

typedef BuildBarLabel<T> = String Function(BarData<T>);

class BarChart<T extends num> extends StatefulWidget {
  final double height;
  final double width;
  final List<BarData<T>> data;
  final BuildBarLabel labelBuilder;

  const BarChart({
    Key key,
    this.height,
    this.width,
    this.data,
    this.labelBuilder,
  }) : super(key: key);

  @override
  _BarChartState<T> createState() => _BarChartState<T>();
}

class _BarChartState<T extends num> extends State<BarChart<T>> {
  ScrollController barScrollController;
  ScrollController labelScrollController;

  num get total {
    num temp = 0;

    widget.data.forEach((item) {
      temp += item.value;
    });

    return temp;
  }

  num get max {
    num temp = 0;

    widget.data.forEach((item) {
      temp = math.max(item.value, temp);
    });

    final avg = (temp / 4.0).floor();

    if (temp > 50) {
      var exponent = avg.toString().length - 1;
      var pow = math.pow(10, exponent);

      var dis = math.max((avg / pow).ceil() * pow, 10);

      return dis * 4;
    }

    return math.max(temp.ceil() % 4 == 0 ? temp.ceil() : 4 * (temp.ceil() ~/ 4 + 1), 4);
  }

  @override
  void initState() {
    super.initState();

    barScrollController = ScrollController();
    labelScrollController = ScrollController();

    barScrollController.addListener(() {
      labelScrollController.jumpTo(barScrollController.offset);
    });
  }

  @override
  void dispose() {
    barScrollController.dispose();
    barScrollController = null;

    labelScrollController.dispose();
    labelScrollController = null;
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      width: widget.width,
      height: widget.height,
      child: LayoutBuilder(
        builder: (context, viewport) {
          final maxHeight = viewport.maxHeight - 15;
          final maxWidth = viewport.maxWidth;

          return Column(
            children: <Widget>[
              Expanded(
                child: Stack(
                  overflow: Overflow.visible,
                  children: <Widget>[
                    buildGrid(),
                    Container(
                      width: maxWidth,
                      height: maxHeight,
                      margin: EdgeInsets.only(left: 35),
                      child: ListView.builder(
                        controller: barScrollController,
                        scrollDirection: Axis.horizontal,
                        padding: EdgeInsets.only(top: 15),
                        itemBuilder: (context, index) {
                          final current = widget.data[index];
                          final percentage = current.value == 0 ? 0 : current.value / max;
                          final height = (maxHeight - 30) * percentage;

                          return Row(
                            mainAxisSize: MainAxisSize.min,
                            crossAxisAlignment: CrossAxisAlignment.end,
                            children: <Widget>[
                              Stack(
                                overflow: Overflow.visible,
                                alignment: Alignment.bottomCenter,
                                fit: StackFit.loose,
                                children: <Widget>[
                                  Padding(
                                    padding: EdgeInsets.symmetric(horizontal: 17.5),
                                    child: Container(
                                      width: 8,
                                      height: height,
                                      decoration: BoxDecoration(
                                        borderRadius: BorderRadius.all(
                                          Radius.circular(8),
                                        ),
                                        gradient: LinearGradient(
                                          colors: _colors[index % _colors.length],
                                          begin: Alignment.topCenter,
                                          end: Alignment.bottomCenter,
                                        ),
                                      ),
                                    ),
                                  ),
                                  Positioned(
                                    top: -12,
                                    child: Text(
                                      widget.labelBuilder == null ? '${current.value}' : widget.labelBuilder(current),
                                      style: TextStyleConstant().blue_18,
                                    ),
                                  ),
                                ],
                              ),
                            ],
                          );
                        },
                        itemCount: widget.data.length,
                      ),
                    ),
                  ],
                ),
              ),
              Container(
                height: 30,
                margin: EdgeInsets.only(
                  left: 35,
                ),
                child: ListView.builder(
                  physics: NeverScrollableScrollPhysics(),
                  controller: labelScrollController,
                  scrollDirection: Axis.horizontal,
                  itemBuilder: (context, index) {
                    var current = widget.data[index];

                    return Container(
                      width: 43,
                      child: Text(
                        current?.label ?? '',
                        textAlign: TextAlign.center,
                        style: TextStyleConstant().normal_3_20,
                        maxLines: 2,
                        overflow: TextOverflow.ellipsis,
                      ),
                    );
                  },
                  itemCount: widget.data.length,
                ),
              ),
            ],
          );
        },
      ),
    );
  }

  Widget buildGrid() {
    List<Widget> children = [];

    var temp = max ~/ 4;

    for (int i = 0; i < 5; i++) {
      var value = (4 - i) * temp;
      String str = value.toString();

      if (value > 10000) {
        str = '${value / 10000}万';
      }

      children.add(Container(
        child: Stack(
          overflow: Overflow.visible,
          children: <Widget>[
            Row(
              children: <Widget>[
                Container(width: 40),
                Expanded(
                  child: Container(
                    height: 1,
                    color: ColorConstant.f7f7ff,
                  ),
                ),
              ],
            ),
            Positioned(
              left: 0,
              top: 0,
              child: Align(
                alignment: Alignment(0, -2),
                heightFactor: 2,
                child: Container(
                  width: 40,
                  child: Text(
                    '$str',
                    textAlign: TextAlign.center,
                    style: TextStyle(
                      color: ColorConstant.e6e6,
                      fontSize: 22.sp,
                    ),
                  ),
                ),
              ),
            ),
          ],
        ),
      ));
    }

    return Container(
      padding: EdgeInsets.only(top: 15),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: children,
      ),
    );
  }
}

class BarData<T> {
  String label;
  T value;
  Color color;

  BarData(this.label, this.value, this.color);
}
